package raft

import (
	"math/rand"
	"time"
)

// The ticker go routine starts a new election if this peer hasn't received
// heartsbeats recently.
func (rf *Raft) ticker() {
	for rf.killed() == false {
		rf.mu.Lock()
		st := rf.state
		rf.mu.Unlock()
		if st == 0 {
			select {
			case state := <-rf.changeState:
				{
					rf.mu.Lock()
					rf.state = state
					rf.mu.Unlock()
				}
			case <-time.After(time.Duration(rand.Intn(150)+300) * time.Millisecond):
				{
					rf.mu.Lock()
					rf.state = 1
					rf.mu.Unlock()
				}
			}
		} else if st == 1 {
			select {
			case state := <-rf.changeState:
				{
					rf.mu.Lock()
					rf.state = state
					rf.mu.Unlock()
				}
			case <-time.After(time.Duration(rand.Intn(150)+300) * time.Millisecond):
				{
					rf.mu.Lock()
					rf.term++
					rf.votedFor = rf.me
					lastIdx, lastTerm := rf.getLastLogIndexAndTerm()
					go rf.vote(rf.term, rf.me, lastIdx, lastTerm)
					rf.mu.Unlock()
				}
			}
		} else {
			// 成为leader要马上发送心跳
			rf.mu.Lock()
			go rf.heartBeats(rf.term, rf.me, rf.commitIndex)
			rf.mu.Unlock()
			select {
			case state := <-rf.changeState:
				{
					rf.mu.Lock()
					rf.state = state
					rf.mu.Unlock()
				}
			case <-time.After(100 * time.Millisecond):
			}
		}
	}
}
